import { SearchOutlined } from '@ant-design/icons'
import { Input, Tag, Checkbox, Card } from 'antd'
import { OrderedMap } from 'immutable'
import pick from 'lodash/pick'
import throttle from 'lodash/throttle'
import { Empty } from '@/desktop/components'
import ChooseGroupTags from '@/desktop/components/ChooseGroupTags'
import { AvatarImage } from '@/desktop/components/avatar'
import { colors, breakWord } from '@/desktop/styles'
import { type AccountQywx } from '@/services/qywxs'
import { type ContactInfo } from '../logics'
import { GroupType, useChooseTags, useGroups, useChooseAll } from './choose-target-groups-logics'

export function ChooseTargetGroups({
  qywxs,
  contacts,
  setContacts,
}: {
  qywxs: AccountQywx[]
  contacts: ContactInfo[]
  setContacts: (contacts: ContactInfo[]) => void
}) {
  const { wxids, qywxMap } = useMemo(() => {
    const wxids = qywxs.map(v => v.wxid)
    const qywxMap = OrderedMap(qywxs.map(v => [v.wxid, v]))
    return { wxids, qywxMap }
  }, [qywxs])

  const [choosingTags, setChoosingTags] = useState(false)
  const { tagIds, setTagIds, cancelChooseTag, choosedTags } = useChooseTags()
  const [types, setTypes] = useState<GroupType[]>([])
  const [keyword, setKeyword] = useState('')
  const throttleSetKeyword = useMemo(() => throttle(setKeyword, 200), [])
  const { allGroupsMap, filteredGroups } = useGroups(wxids, tagIds, types, keyword)

  const validChoosedMap = useMemo(
    () => OrderedMap(contacts.filter(info => allGroupsMap.has(info.id)).map(v => [v.id, v])),
    [contacts, allGroupsMap],
  )
  const switchChoose = useCallback(
    (info: ContactInfo) => {
      let map = validChoosedMap
      if (map.has(info.id)) map = map.delete(info.id)
      else map = map.set(info.id, info)
      setContacts([...map.values()])
    },
    [validChoosedMap, setContacts],
  )
  const { hasChoosed, isChoosedAll, chooseAll, chooseReverse, clearChoose } = useChooseAll(
    filteredGroups,
    validChoosedMap,
    setContacts,
  )

  return <>
    <header css={s.filter}>
      <Input
        prefix={<SearchOutlined />}
        placeholder="输入关键字搜索群聊"
        onChange={e => throttleSetKeyword(e.target.value)}
        allowClear
      />
      <div className="filter-by-tags">
        <label>按标签筛选</label>
        <div>
          {choosedTags.map(tag => <Tag
            key={tag.id}
            closable
            onClose={() => cancelChooseTag(tag.id)}
          >
            {tag.name}
          </Tag>)}
          <a onClick={() => setChoosingTags(true)}>选择标签</a>
        </div>
      </div>
      <div className="filter-by-types">
        <label>按类型筛选</label>
        <div>
          <Checkbox.Group
            value={types}
            onChange={values => setTypes(values as GroupType[])}
            options={[
              { label: '群主', value: GroupType.群主 },
              { label: '外部群', value: GroupType.外部群 },
            ]}
          />
        </div>
      </div>
    </header>

    {!filteredGroups.length ? <Empty description="没有匹配的群" /> : null}

    {filteredGroups.length ? (
      <div css={s.chooseAll}>
        <Checkbox
          checked={isChoosedAll}
          indeterminate={hasChoosed && !isChoosedAll}
          onClick={isChoosedAll ? clearChoose : chooseAll}
        />
        <a onClick={chooseAll}>全选</a>
        <span>/</span>
        <a onClick={chooseReverse}>反选</a>
      </div>
    ) : null}

    {filteredGroups.length ? (
      <main css={s.groups}>
        {filteredGroups.map(group => {
          const choosed = validChoosedMap.has(group.id)
          return <Card
            key={group.id}
            onClick={() => switchChoose(pick(group, 'id', 'ownerWxid', 'conversationId'))}
          >
            <Checkbox checked={choosed} />
            <AvatarImage src={group.avatar} size={64} preview={false} />
            <div className="name">
              <span>{group.name}</span>
              {group.isOwner ? <Tag>群主</Tag> : null}
              {group.isExternal ? <Tag>外部群</Tag> : null}
            </div>
            {group.remark ? <div className="remark">{group.remark}</div> : null}
            <div className="pad"></div>
            <div className="qywx">{qywxMap.get(group.ownerWxid)?.friendlyName ?? ''}</div>
          </Card>
        })}
      </main>
    ) : null}

    <ChooseGroupTags
      visible={choosingTags}
      title="选择群标签"
      choosed={tagIds}
      onFinish={tags => {
        if (tags) setTagIds(tags.map(v => v.id))
        setChoosingTags(false)
      }}
    />
  </>
}

const s = {
  filter: css`
    padding-top: 20px;
    .filter-by-tags,
    .filter-by-types {
      align-items: center;
      display: flex;
      margin-top: 12px;
      & > label {
        color: ${colors.gray};
        font-size: 12px;
        margin-right: 12px;
      }
      a {
        font-size: 12px;
      }
      .ant-checkbox + span {
        font-size: 13px;
      }
    }
  `,

  chooseAll: css`
    padding: 30px 0 8px;
    display: flex;
    align-items: center;
    .ant-checkbox-wrapper {
      transform: translateY(-1px);
      margin-right: 2px;
    }
    a {
      font-size: 12px;
      padding: 2px 4px;
    }
    & > span {
      color: ${colors.gray};
    }
  `,

  groups: css`
    column-gap: 20px;
    display: flex;
    flex-wrap: wrap;
    overflow-y: auto;
    row-gap: 20px;
    flex-shrink: 1;
    padding: 6px 0;
    .ant-card {
      width: 180px;
      cursor: pointer;
      transition: box-shadow 0.2s;
      &:hover {
        box-shadow: 0px 2px 6px #f5f5f5;
      }
    }
    .ant-card-body {
      align-items: center;
      display: flex;
      flex-direction: column;
      height: 100%;
      line-height: 1.4;
      padding: 12px;
      position: relative;
      text-align: center;
    }
    .ant-checkbox-wrapper {
      position: absolute;
      left: 12px;
      top: 6px;
    }
    .ant-card.offline .ant-image {
      filter: grayscale(1);
    }
    .offline-text {
      color: ${colors.gray};
      font-size: 12px;
      position: absolute;
      right: 6px;
      top: 9px;
    }
    .name {
      ${breakWord};
      margin-bottom: 12px;
      margin-top: 12px;
      line-height: 1.4em;
      .ant-tag {
        background-color: #fff;
        margin: 0;
        transform-origin: center right;
        transform: scale(0.8);
      }
    }
    .remark {
      ${breakWord};
      color: ${colors.gray};
      font-size: 12px;
      margin-bottom: 12px;
      flex: 1;
    }
    .pad {
      flex: 1;
    }
    .qywx {
      ${breakWord};
      color: #3f77fa;
      font-size: 12px;
    }
  `,
}
